/////////////////////////////////////////////////////
// File Name: crc32_v1.v
// Author: zeping fan
// mail:   zpfan007@163.com
// Created Time: 2023年06月01日 星期四 15时49分35秒
/////////////////////////////////////////////////////

module  crc32(

clk,
rstn,
data,
vld,
init,
calc,
crc_reg,
crc

);

input               clk;
input               rstn;
input       [7:0]   data;
input               vld;
input               init;
input               calc;
output      [31:0]  crc_reg;
output  reg [7:0]   crc;


reg     [31:0]  lfsr_q;    
wire    [2:0]   ctrl;
wire    [31:0]  lfsr_c;
wire    [7:0]   din;

assign din[7:0] = {data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7]};

assign ctrl[2:0] = {init,calc,vld};

assign crc_reg[31:0] = lfsr_q[31:0];

always @(posedge clk or negedge rstn)begin
    if(!rstn)begin
        lfsr_q[31:0] <= 32'b0;
        crc[7:0] <= 8'b0;
    end
    else begin
        case(ctrl)
            3'b000,3'b001:begin
                lfsr_q[31:0] <= lfsr_q[31:0];
                crc[7:0] <= crc[7:0];
            end
            3'b010:begin
                lfsr_q[31:0] <= {lfsr_q[23:0],8'hff};
                crc[7:0] <= ~{lfsr_q[16],lfsr_q[17],lfsr_q[18],lfsr_q[19],lfsr_q[20],lfsr_q[21],lfsr_q[22],lfsr_q[23]};
            end
            3'b011:begin
                lfsr_q[31:0] <= lfsr_c[31:0];
                crc[7:0] <= ~{lfsr_c[24],lfsr_c[25],lfsr_c[26],lfsr_c[27],lfsr_c[28],lfsr_c[29],lfsr_c[30],lfsr_c[31]}; 
            end
            3'b100,3'b101,3'b110,3'b111:begin
                lfsr_q[31:0] <= 32'hffff_ffff;
                crc[7:0] <= crc[7:0];
            end
        endcase
    end
end


//crc32 gen
assign lfsr_c[0] = din[6] ^ din[0] ^ lfsr_q[24] ^ lfsr_q[30];
assign lfsr_c[1] = din[7] ^ din[6] ^ din[1] ^ din[0] ^ lfsr_q[24] ^ lfsr_q[25] ^ lfsr_q[30] ^ lfsr_q[31];
assign lfsr_c[2] = din[7] ^ din[6] ^ din[2] ^ din[1] ^ din[0] ^ lfsr_q[24] ^ lfsr_q[25] ^ lfsr_q[26] ^ lfsr_q[30] ^ lfsr_q[31];
assign lfsr_c[3] = din[7] ^ din[3] ^ din[2] ^ din[1] ^ lfsr_q[25] ^ lfsr_q[26] ^ lfsr_q[27] ^ lfsr_q[31];
assign lfsr_c[4] = din[6] ^ din[4] ^ din[3] ^ din[2] ^ din[0] ^ lfsr_q[24] ^ lfsr_q[26] ^ lfsr_q[27] ^ lfsr_q[28] ^ lfsr_q[30];
assign lfsr_c[5] = din[7] ^ din[6] ^ din[5] ^ din[4] ^ din[3] ^ din[1] ^ din[0] ^ lfsr_q[24] ^ lfsr_q[25] ^ lfsr_q[27] ^ lfsr_q[28] ^ lfsr_q[29] ^ lfsr_q[30] ^ lfsr_q[31];
assign lfsr_c[6] = din[7] ^ din[6] ^ din[5] ^ din[4] ^ din[2] ^ din[1] ^ lfsr_q[25] ^ lfsr_q[26] ^ lfsr_q[28] ^ lfsr_q[29] ^ lfsr_q[30] ^ lfsr_q[31];
assign lfsr_c[7] = din[7] ^ din[5] ^ din[3] ^ din[2] ^ din[0] ^ lfsr_q[24] ^ lfsr_q[26] ^ lfsr_q[27] ^ lfsr_q[29] ^ lfsr_q[31];
assign lfsr_c[8] = din[4] ^ din[3] ^ din[1] ^ din[0] ^ lfsr_q[0] ^ lfsr_q[24] ^ lfsr_q[25] ^ lfsr_q[27] ^ lfsr_q[28];
assign lfsr_c[9] = din[5] ^ din[4] ^ din[2] ^ din[1] ^ lfsr_q[1] ^ lfsr_q[25] ^ lfsr_q[26] ^ lfsr_q[28] ^ lfsr_q[29];
assign lfsr_c[10] = din[5] ^ din[3] ^ din[2] ^ din[0] ^ lfsr_q[2] ^ lfsr_q[24] ^ lfsr_q[26] ^ lfsr_q[27] ^ lfsr_q[29];
assign lfsr_c[11] = din[4] ^ din[3] ^ din[1] ^ din[0] ^ lfsr_q[3] ^ lfsr_q[24] ^ lfsr_q[25] ^ lfsr_q[27] ^ lfsr_q[28];
assign lfsr_c[12] = din[6] ^ din[5] ^ din[4] ^ din[2] ^ din[1] ^ din[0] ^ lfsr_q[4] ^ lfsr_q[24] ^ lfsr_q[25] ^ lfsr_q[26] ^ lfsr_q[28] ^ lfsr_q[29] ^ lfsr_q[30];
assign lfsr_c[13] = din[7] ^ din[6] ^ din[5] ^ din[3] ^ din[2] ^ din[1] ^ lfsr_q[5] ^ lfsr_q[25] ^ lfsr_q[26] ^ lfsr_q[27] ^ lfsr_q[29] ^ lfsr_q[30] ^ lfsr_q[31];
assign lfsr_c[14] = din[7] ^ din[6] ^ din[4] ^ din[3] ^ din[2] ^ lfsr_q[6] ^ lfsr_q[26] ^ lfsr_q[27] ^ lfsr_q[28] ^ lfsr_q[30] ^ lfsr_q[31];
assign lfsr_c[15] = din[7] ^ din[5] ^ din[4] ^ din[3] ^ lfsr_q[7] ^ lfsr_q[27] ^ lfsr_q[28] ^ lfsr_q[29] ^ lfsr_q[31];
assign lfsr_c[16] = din[5] ^ din[4] ^ din[0] ^ lfsr_q[8] ^ lfsr_q[24] ^ lfsr_q[28] ^ lfsr_q[29];
assign lfsr_c[17] = din[6] ^ din[5] ^ din[1] ^ lfsr_q[9] ^ lfsr_q[25] ^ lfsr_q[29] ^ lfsr_q[30];
assign lfsr_c[18] = din[7] ^ din[6] ^ din[2] ^ lfsr_q[10] ^ lfsr_q[26] ^ lfsr_q[30] ^ lfsr_q[31]; 
assign lfsr_c[19] = din[7] ^ din[3] ^ lfsr_q[11] ^ lfsr_q[27] ^ lfsr_q[31];
assign lfsr_c[20] = din[4] ^ lfsr_q[12] ^ lfsr_q[28];
assign lfsr_c[21] = din[5] ^ lfsr_q[13] ^ lfsr_q[29];
assign lfsr_c[22] = din[0] ^ lfsr_q[14] ^ lfsr_q[24];
assign lfsr_c[23] = din[6] ^ din[1] ^ din[0] ^ lfsr_q[15] ^ lfsr_q[24] ^ lfsr_q[25] ^ lfsr_q[30];
assign lfsr_c[24] = din[7] ^ din[2] ^ din[1] ^ lfsr_q[16] ^ lfsr_q[25] ^ lfsr_q[26] ^ lfsr_q[31];
assign lfsr_c[25] = din[3] ^ din[2] ^ lfsr_q[17] ^ lfsr_q[26] ^ lfsr_q[27];
assign lfsr_c[26] = din[6] ^ din[4] ^ din[3] ^ din[0] ^ lfsr_q[18] ^ lfsr_q[24] ^ lfsr_q[27] ^ lfsr_q[28] ^ lfsr_q[30];
assign lfsr_c[27] = din[7] ^ din[5] ^ din[4] ^ din[1] ^ lfsr_q[19] ^ lfsr_q[25] ^ lfsr_q[28] ^ lfsr_q[29] ^ lfsr_q[31];
assign lfsr_c[28] = din[6] ^ din[5] ^ din[2] ^ lfsr_q[20] ^ lfsr_q[26] ^ lfsr_q[29] ^ lfsr_q[30];
assign lfsr_c[29] = din[7] ^ din[6] ^ din[3] ^ lfsr_q[21] ^ lfsr_q[27] ^ lfsr_q[30] ^ lfsr_q[31];
assign lfsr_c[30] = din[7] ^ din[4] ^ lfsr_q[22] ^ lfsr_q[28] ^ lfsr_q[31];
assign lfsr_c[31] = din[5] ^ lfsr_q[23] ^ lfsr_q[29];


endmodule 
